/** 自定义的按键相关函数的模块
  By setycyas @2023-01-14
*/

/** 全局变量 
*/
global __MyKey_autoFireKey := "" ;触发连发的按键,需要用MyKey_setAutoFire()函数设定
global __MyKey_fireKey := "" ;连发的目标按键,默认设定为空,需要用MyKey_setAutoFire()函数设定
global __MyKey_autoFireDuration := 30 ;连发按键的按下时间,需要用MyKey_setAutoFire()函数设定
global __MyKey_autoFireDelay := 30 ;连发按键的延时,需要用MyKey_setAutoFire()函数设定
global __MyKey_autoFireFirstDelay := 0 ;首发延时,设定为0则不使用.有时连发过程中需要第一发速度更慢
global __MyKey_autoFireSwitch := +0 ;是否执行连发的开关,+0表示关闭
global __MyKey_autoFireState := +1 ;连发单发设定,+0表示单发,+1表示连发

/** 内部函数 
*/
;开始连发,也可能模拟单发
__MyKey_autoFireOn(){
  ;未设定连发键的情况
  if (__MyKey_fireKey == "") 
    return
  ;单发的情况
  if (__MyKey_autoFireState == +0) {
    Send, {%__MyKey_fireKey% down}
    return
  } else {
    __MyKey_autoFireSwitch := +1
    if (__MyKey_autoFireFirstDelay != 0){ ;有首发延时的情况
      send, {%__MyKey_fireKey% down}
      sleep, %__MyKey_autoFireDuration%
      Send, {%__MyKey_fireKey% up}
      sleep, %__MyKey_autoFireFirstDelay%
    }
    while (__MyKey_autoFireSwitch) {
      Send, {%__MyKey_fireKey% down}
      sleep, %__MyKey_autoFireDuration%
      Send, {%__MyKey_fireKey% up}
      sleep, %__MyKey_autoFireDelay%
    }
  }
}
;中止连发,或模拟单发的按键弹起
__MyKey_autoFireOff(){
  if (__MyKey_autoFireState == +0){ ;单发的情况
    Send, {%__MyKey_fireKey% up}
    return
  } else { ;连发的情况
    __MyKey_autoFireSwitch := +0
  }
}

/** 导出的函数 
*/
;按键后放开按键函数, key为按键, pressDuration为持续时间
MyKey_press(key, pressDuration := 100){
  send, {%key% down}
  sleep, %pressDuration%
  send, {%key% up}
}

;连续按键最后才一起放开的函数,keys为按键[],delays为延时[]长度应该比keys小1,duration则是全部按下之后持续的时间
MyKey_pressKeys(keys, delays, duration := 50){
  for index, val in keys{
    send {%val% down}
    if (index < keys.Count())
      sleep, % delays[index]
  }
  sleep, %duration%
  for index, val in keys{
    send {%val% up}
  }
}

;等待按键key放开,等待waitTime毫秒,每waitDuration毫秒检查一次,若发现按键放开返回1,等待完毕未放开返回0
MyKey_waitKeyUp(key, waitTime, waitDuration := 100){
  local temp1 := 0 ;计算总等待时间
  local delta := 0 ;下一次等待时间
  while (temp1 < waitTime) {
    delta := (waitTime-temp1 > waitDuration) ? (waitDuration) : (waitTime-temp1)
    if (!GetKeyState(key)) {
      return 1
    }
    sleep ,%delta%
    temp1 := temp1+delta
  }
  return 0
}

;连续输入指令,相邻的两个key有重叠时间,等前一个key放开时,后面的key才会输入,keys和delays长度应该相同
MyKey_inputSkill(keys, delays){
  local i, v, curKey, curDelay, lastKey
  for i, v in keys {
    curKey := v
    curDelay := delays[i]
    if (i > 1)
      lastKey := keys[i-1]
    else
      lastKey := 0
    send {%curKey% down}
    sleep, %curDelay%
    if lastKey
      send {%lastKey% up}
    if (i = keys.Count())
      send {%curKey% up}
    sleep, 30 ;放开前一个按键与输入后一个按键之间需要有一点时间缓冲
  }
  
}

;一般的连发,并非使用内部的autoFireSwitch,效率要低一点
MyKey_normalAutoFire(fireKey, autoFireKey, duration := 30, delay := 30){
  MyKey_press(fireKey, duration)
  sleep, %delay%
  while (GetKeyState(autoFireKey)){
    MyKey_press(fireKey, duration)
    sleep, %delay%
  }
}

;获取与设定是否连发
MyKey_getAutoFireState() {
  return __MyKey_autoFireState
}
MyKey_setAutoFireState(state) {
  __MyKey_autoFireState := state
}

;设定连发键到指定的exe
MyKey_setAutoFire(exeTitle, fireKey, autoFireKey, duration := 30, delay := 30, firstDelay := 0){
  __MyKey_autoFireKey := autoFireKey ;触发连发的按键
  __MyKey_fireKey := fireKey ;连发的目标按键,默认设定为空
  __MyKey_autoFireDuration := duration ;连发按键的按下时间
  __MyKey_autoFireDelay := delay ;连发按键的延时
  __MyKey_autoFireFirstDelay := firstDelay ;连发按键的首发延时,0表示不设定
  Hotkey, IfWinActive, ahk_exe %exeTitle%
  Hotkey, %__MyKey_autoFireKey%, __MyKey_autoFireOn
  Hotkey, %__MyKey_autoFireKey% up, __MyKey_autoFireOff
  Hotkey, IfWinActive
}